<!--
 * @Description:
-->
<script lang="ts" setup>
import type { PropType } from 'vue'
import { computed, unref } from 'vue'
import { asyncComputed } from '@vueuse/core'
import { omit } from 'lodash-es'
import { Col, Divider, FormItem, Tooltip } from 'ant-design-vue'
import { componentMap } from '../../core/formItemConfig'
import type { IFormConfig, IVFormComponent } from '../../typings/v-form-component'
import { handleAsyncOptions } from '../../utils'
import { useFormModelState } from '../../hooks/useFormDesignState'
import { Icon } from '@/components/Icon'

const props = defineProps({
  formData: {
    type: Object,
    default: () => ({}),
  },
  schema: {
    type: Object as PropType<IVFormComponent>,
    required: true,
  },
  formConfig: {
    type: Object as PropType<IFormConfig>,
    required: true,
  },
})

const emit = defineEmits(['update:form-data', 'change'])

const { formModel: formData1, setFormModel } = useFormModelState()
const colPropsComputed = computed(() => {
  const { colProps = {} } = props.schema
  return colProps
})
const formItemProps = computed(() => {
  const { formConfig } = unref(props)
  let { field, required, rules, labelCol, wrapperCol } = unref(props.schema)
  const { colon } = props.formConfig

  const { itemProps } = unref(props.schema)

  // <editor-fold desc="布局属性">
  labelCol = labelCol || (formConfig.layout === 'horizontal'
    ? formConfig.labelLayout === 'flex'
      ? { style: `width:${formConfig.labelWidth}px` }
      : formConfig.labelCol
    : {})

  wrapperCol = wrapperCol || (formConfig.layout === 'horizontal'
    ? formConfig.labelLayout === 'flex'
      ? { style: 'width:auto;flex:1' }
      : formConfig.wrapperCol
    : {})

  const style
          = formConfig.layout === 'horizontal' && formConfig.labelLayout === 'flex'
            ? { display: 'flex' }
            : {}

  /**
   * 将字符串正则格式化成正则表达式
   */

  const newConfig = Object.assign(
    {},
    {
      name: field,
      style: { ...style },
      colon,
      required,
      rules,
      labelCol,
      wrapperCol,
    },
    itemProps,
  )
  if (!itemProps?.labelCol?.span)
    newConfig.labelCol = labelCol

  if (!itemProps?.wrapperCol?.span)
    newConfig.wrapperCol = wrapperCol

  if (!itemProps?.rules)
    newConfig.rules = rules

  return newConfig
}) as Recordable<any>

const componentItem = computed(() => componentMap.get(props.schema.component as string))

// console.log('component change:', props.schema.component, componentItem.value);
function handleClick(schema: IVFormComponent) {
  if (schema.component === 'Button' && schema.componentProps?.handle)
    emit(schema.componentProps?.handle)
}
/**
 * 处理异步属性，异步属性会导致一些属性渲染错误，如defaultValue异步加载会导致渲染不出来，故而此处只处理options，treeData，同步属性在cmpProps中处理
 */
const asyncProps = asyncComputed(async () => {
  let { options, treeData } = props.schema.componentProps ?? {}
  if (options)
    options = await handleAsyncOptions(options)
  if (treeData)
    treeData = await handleAsyncOptions(treeData)
  return {
    options,
    treeData,
  }
})

/**
 * 处理同步属性
 */
const cmpProps = computed(() => {
  const isCheck
          = props.schema && ['Switch', 'Checkbox', 'Radio'].includes(props.schema.component)
  const { field } = props.schema

  let { disabled, ...attrs }
          = omit(props.schema.componentProps, ['options', 'treeData']) ?? {}

  disabled = props.formConfig.disabled || disabled

  return {
    ...attrs,
    disabled,
    [isCheck ? 'checked' : 'value']: formData1.value[field!],
  }
})

const handleChange = function (e) {
  const isCheck = ['Switch', 'Checkbox', 'Radio'].includes(props.schema.component)
  const target = e ? e.target : null
  const value = target ? (isCheck ? target.checked : target.value) : e
  setFormModel(props.schema.field!, value)
  emit('change', value)
}
</script>

<template>
  <Col v-bind="colPropsComputed">
    <FormItem v-bind="{ ...formItemProps }">
      <template v-if="!formItemProps.hiddenLabel && schema.component !== 'Divider'" #label>
        <Tooltip>
          <span>{{ schema.label }}</span>
          <template v-if="schema.helpMessage" #title>
            <span>{{ schema.helpMessage }}</span>
          </template>
          <Icon v-if="schema.helpMessage" class="ml-5" icon="ant-design:question-circle-outlined" />
        </Tooltip>
      </template>

      <slot
        v-if="schema.componentProps && schema.componentProps?.slotName"
        :name="schema.componentProps.slotName"
        v-bind="schema"
      />
      <Divider
        v-else-if="schema.component === 'Divider' && schema.label && !formItemProps.hiddenLabel"
      >
        {{ schema.label }}
      </Divider>
      <!-- 部分控件需要一个空div -->
      <div>
        <component
          :is="componentItem"
          class="v-form-item-wrapper"
          v-bind="{ ...cmpProps, ...asyncProps }"
          :schema="schema"
          :style="schema.width ? { width: schema.width } : {}"
          @change="handleChange"
          @click="handleClick(schema)"
        />
      </div>

      <span v-if="['Button'].includes(schema.component)">{{ schema.label }}</span>
    </FormItem>
  </Col>
</template>

<style lang="less" scoped>
  .ml-5 {
    margin-left: 5px;
  }

  // form字段中的标签有ant-col，不能使用width:100%
  :deep(.ant-col) {
    width: auto;
  }

  .ant-form-item:not(.ant-form-item-with-help) {
    margin-bottom: 20px;
  }

  // .w-full {
  //   width: 100% !important;
  // }
</style>
